Leetcode第一题:两数之和(3种语言) | 您所在的位置:网站首页 › python 两数之和 › Leetcode第一题:两数之和(3种语言) |
Leetcode第一题:两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 标注:仅在Python解法做详细分析,c++与java如无特别需要注意的地方不做分析。 一、Python解法解法2,3参考了linfeng886的博客 解法1:暴力搜索 class Solution: def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ #对nums每个元素循环 for i in range(len(nums)): #从nums[i]的下一个开始找 for j in range(i+1,len(nums)): #如果找到了就返回值 if nums[i]+nums[j]==target: return i,j分析:代码十分简单,就是首先用i在数组里循环一轮,在每个i循环下,去从剩下的元素找target-nums[i]的值。如果找到了,就return i,j两个数。(程序假设一定可以找的到) 来看看运行结果: 此代码的运行问题在于:
关于hash table(哈希表),简单来说就是存有键值对key,value的一种数据结构,对于熟悉Python的人来说,常见的字典就是一种hash table。它的查找速度是很快的,可以理解为O(1)。所以这里相当于在解法2的基础上做了一个改进。解法2 是在空间不变的前提下,在i循环时,直接在列表里查找是否含有target-nums[0]的元素,而列表的查找速度是远不如hash table。所以解法三的关键就在于,查找的任务在字典中进行而不在list中进行(有待商榷) 代码: class Solution: def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ #遍历一个i,就把nums[i]放在字典里。之后i不断相加,总会碰到 #target - nums[i]在字典里的情况。碰到的时候return即可。这里注意到先return的是dict[a],再是当前的i,原因就是dict里存的value都是以前遍历过的i,所以它比当前的i小,按从小到大的顺序所以这样排。 dict = {} for i in range(len(nums)): a = target - nums[i] if a in dict: return dict[a],i else: dict[nums[i]] = i运行结果: 解法2,3参照了官方解法twosum 以及菜鸟教程java数组篇 Pythonliast与java数组区别 https://blog.csdn.net/wu1226419614/article/details/80870120 关于hashmap数据类型 https://www.cnblogs.com/hello-yz/p/3712610.html 解法1:暴力搜索代码: class Solution { public int[] twoSum(int[] nums, int target) { int[] a = new int[2]; for(int i=0;i if(nums[i]+nums[j]==target){ a[0] = i; a[1] = j; //return new int[] {i,j}; } } } return a; } }
在这里和Python的3种解法做一个比较。可以看到两种语言的解法1是完全相同的。但是解法2上,会有一些区别。之后解法3又是完全相同的。为什么解法2会和Python解法2有区别呢? 先回顾下Python解法2:通过i循环列表,直接判断target - nums[i]是否在列表里,在的话,就直接返回i,与list.index(target-nums[I])。这里我们用了Python内置函数index。可以方便的获取到索引,而对于java的数组,并没有那么方便获取数组元素索引的函数。这里有一个很好的比较,从中可以知道java对于数组有一个binarySearch的查找方法,而它本身就是用二分法查找实现的,所以只适用于有序数组。同时若再用一次for循环获取索引,得不偿失。那不如多用一次for循环把索引与数值一一对应起来,用类似Python字典的方式,这样查找的更快-----hashmap 代码: class Solution { public int[] twoSum(int[] nums, int target) { int[] b = new int[2]; HashMap map = new HashMap(); for(int i=0;i int a = target - nums[j]; if(map.containsKey(a) && j!=map.get(a)){ b[0] = j; b[1] = map.get(a); return b; //return new int[] {j,map.get(a)}; } } return b; } }
此解法思想与Python解法3如出一辙,是一模一样的,唯一区别在于Python使用字典做查找,Java使用HashMap做查找。因此本解法不做过多说明。 代码: class Solution { public int[] twoSum(int[] nums, int target) { HashMap map = new HashMap(); for(int i=0;i return new int[] {map.get(nums[i]),i}; } map.put(target-nums[i],i); } return new int[]{1,1,1}; } }
有了上述两种语言的解答做铺垫,我觉得C++解法思路就会清晰很多了。 解法1:暴力搜索直接看代码: class Solution { public: vector twoSum(vector& nums, int target) { //vector类型为长度可变的数组,更灵活。需要#include vector a; //int a[2];这里指定返回的是verctor类型,故这里不能用普通数组array for(int i=0;i if(nums[i]+nums[j]==target){ //在a的最后添加元素 a.push_back(i); a.push_back(j); //a[0] = i; //a[1] =j; return a; } } } //注意这里和java不一样,不需要一定要返回一个vector了。虽然该类要求有一个返回值 } };
3.关于数组作为函数的形参。 本例中是这样写的: vector twoSum(vector& nums, int target) { //insert your code }或者这样写: vector twoSum(vector &nums, int target) { //insert your code }或者: vector twoSum(vector nums, int target) { //insert your code }具体可查看菜鸟教程关于数组做形参的讲解 解法2:两次map(非哈希表)这里注意的是用的是c++的map实现的key,value配对。而c++中还有hash_map,即hash table。二者的区别是: hash_map采用hash表存储,map一般采用红黑树(RB Tree)实现。因此其内存数据结构是不一样的。 二者区别具体可查看 zhenyusoso的博客与Miles-的博客。 先来看map实现的代码: class Solution { public: vector twoSum(vector& nums, int target) { vector a; map map; //hash_map hp; for(int i=0;i if(map.count(target-nums[j])==1 && map[target-nums[j]]!=j){ a.push_back(j); a.push_back(map[target-nums[j]]); return a; } } return a; } };
同时用find方法判别hash_map是否含有想要的key。 hash_map hp; if(hp.find(target-nums[j])!=hp.end() && hp[target-nums[j]]!=j){ //代码区 } 解法3:1次map(非哈希表)这个就没有什么要分析的了,和上面两种语言的解法三一模一样。 class Solution { public: vector twoSum(vector& nums, int target) { vector a; map map; for(int i=0;i a.push_back(map[target-nums[i]]); a.push_back(i); return a; } else{ map[nums[i]] = i; } } return a; } };
ps:后面的刷题笔记应该会3种语言分开记录,这样一篇文章太长,容易产生厌倦感。 |
CopyRight 2018-2019 实验室设备网 版权所有 |